package main

import (
	"bytes"
	"fmt"
	"sync"
	"time"
)

//可以用来goroutine之间的信息传递，同步内存访问

//声明一个channel，声明的类型是空接口，因此它的类型是interface{}
var dataStream chan interface{}
//使用内置的make函数实例化channel
dataStream = make(chan interface{})

//声明和实例化一个只能读取的channel
var dataStream <-chan interface{}
dataStream := make(<-chan interface{})

//声明和实例化一个只能发送的channel
var dataStream chan<- interface{}
dataStream := make(chan<- interface{})

//GO语言隐式地将双向channel转换为单向channel
var receiveChan <-chan interface{}
var sendChan chan<- interface{}
dataStream := make(chan interface{})
//转换，有效地语法
receiveChan = dataStream
sendChan = dataStream

//整数channel地例子
intStream := make(chan int)

示例：
stringStream := make(chan string)
go func() {
	stringStream <- "Hello channels!"  //将字符串文本传递到 stringStream channel
}()
fmt.Println(<-stringStream)    //读取channel 地字符串字面量并将其打印到 stdout

//使用close关键字关闭一个channel
valueStream := make(chan interface{})
close(valueStream)

//从关闭地channel中读取数据
valueStream := make(chan interface{})
close(valueStream)
integer,ok := <-valueStream    //从已经关闭地数据流中读取数据
fmt.Printf("(%v): %v",ok,integer)

//通过range关键作为参数遍历(与for语句一起使用),并且在channel关闭时自动中断循环
intStream := make(chan int)
go func() {
	defer close(intStream) //确保在goroutine退出之前channel是关闭地，常见地模式
	for i:=1;i<=5:i++ {
		intStream <- i
	}
}()

for integer := range intStream {   //遍历intStream
fmt.Printf("%v",integer)
}
//range方法不会返回第二个布尔值，处理一个已关闭地channel地细节可以让你保持循环简洁
//关闭channel也是一种同时给多个goroutine发信号地方法


//示例：
//在同一时间，同时打开多个goroutine
begin := make(chan interface{})
var wg sync.WaitGroup
for i:=0;i<5;i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
<-begin    //goroutine会一直等待，知道它被告知可以继续运行
fmt.Printf("%v has begun\n",i)
}(i)
}
fmt.Println("Unblocking goroutines...")
close(begin)   //关闭channel，从而同时打开所有的goroutine
wg.Wait()


//创建buffered channel
//创建一个有4个容量的缓冲channel，可以把4个东西放到channel上，不用管它是否能被读取
var dataStream chan interface{}
dataStream = make(chan interface{},4)

//缓冲channel是一个内存中的FIFO队列，用于并发进程进行通信

//示例：
var stdoutBuffer bytes.Buffer  //创建一个内存缓冲区，减少输出的不确定性，
defer stdoutBuffer.WriteTo(os.Stdout)  //确保在进程退出之前缓冲区的内容需要被写入到stdout

intStream := make(chan int,4)  //创建一个具有一个容量的缓冲channel
go func() {
	defer close(intStream)
	defer fmt.Fprintln(&stdoutBuffer,"Producer Done.")
	for i:=0;i<5;i++ {
		fmt.Fprintf(&stdoutBuffer,"Sending: %d\n",i)
		intStream <- i
	}
}()

for integer := range intStream {
fmt.Fprintf(&stdoutBuffer,"Received %v.\n",integer)
}



//创建一个拥有channel的groutine,以及一个处理channel阻塞和关闭的消费者
chanOwner := func() <-chan int {
	resultStream := make(chan int,5)   //实例化一个缓冲channel，数量为5
	go func() {    //启动一个匿名的goroutine，在resultStream上执行写操作
		defer close(resultStream)  //确保执行完resultStream就会关闭
		fo i:=0;i<=5;i++ {
			resultStream <- i
		}
	}()
	return resultStream    //返回channel,返回值被声明为一个只读channel,resultStream将隐式地转换为只读消费者
}

resultStream := chanOwner()
for result := range resultStream { //遍历resultStream
fmt.Printf("Received: %d\n",result)
}
fmt.Println("Done receiving!")



select 语句
start := time.Now()
c := make(chan interface{})
go func() {
	time.Sleep(5*time.Second)
	close(c)   //等待5s后关闭channel
}()

fmt.Println("Blocking on read...")
select {
case <-c:  //尝试在channel上读取数据
fmt.Printf("Unblocked %v later.\n",time.Since(start))
}



















